﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;

namespace Pokerist
{
    public class UtilityHelper
    {
        string[] ResultShuffle;

        public string GetActivateString()
        {
            RegistryKey lstKeyVal;
            string strVal = "";
            string[] lstVal;
            try
            {

                lstKeyVal = Registry.LocalMachine.OpenSubKey("HARDWARE\\DESCRIPTION\\System");
                lstVal = (string[])lstKeyVal.GetValue("SystemBiosVersion");
                for (int i = 0; i < lstVal.Length; i++) strVal += lstVal[i].Trim();
                lstKeyVal.Close();
                lstKeyVal = Registry.LocalMachine.OpenSubKey("HARDWARE\\DESCRIPTION\\System\\BIOS");
                strVal += lstKeyVal.GetValue("SystemSKU").ToString();
                strVal += lstKeyVal.GetValue("BIOSVersion").ToString();
                lstKeyVal.Close();
                lstKeyVal = Registry.LocalMachine.OpenSubKey("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
                strVal += lstKeyVal.GetValue("Identifier").ToString();
                strVal += lstKeyVal.GetValue("ProcessorNameString").ToString();
                lstKeyVal.Close();
            }
            catch
            {
                lstKeyVal = null;
            }
            return strVal;
        }

        private string EncryptData(string Data)
        {
            try
            {
                byte[] PP = Encoding.Unicode.GetBytes("POKERIST(C)HAOVO");
                byte[] DataByte = Encoding.Unicode.GetBytes(Data);
                HashAlgorithm HashPassword = HashAlgorithm.Create("MD5");
                byte[] V = new byte[0x10];
                RijndaelManaged EncryptData = new RijndaelManaged();
                EncryptData.Key = HashPassword.ComputeHash(PP);
                ICryptoTransform encryptor = EncryptData.CreateEncryptor(EncryptData.Key, V);
                MemoryStream ms = new MemoryStream();
                CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
                cs.Write(DataByte, 0, DataByte.Length);
                cs.FlushFinalBlock();
                byte[] Result = ms.ToArray();
                ms.Close();
                cs.Close();
                EncryptData.Clear();
                return Convert.ToBase64String(Result);
            }
            catch
            {
                return "";
            }
        }

        private void ShuffleString(string strVal, int lvl)
        {
            if (strVal.Length < 1) return;
            if (strVal.Length == 1)
            {
                ResultShuffle[lvl] += strVal;
                return;
            }

            ResultShuffle[lvl] += strVal[(strVal.Length / 2) + (strVal.Length % 2) - 1].ToString();
            ShuffleString(strVal.Substring(0, (strVal.Length / 2) + (strVal.Length % 2) - 1), lvl + 1);
            ShuffleString(strVal.Substring((strVal.Length / 2) + (strVal.Length % 2)), lvl + 1);
        }

        public string GenerateCode(string strOrg)
        {
            ResultShuffle = new string[120];
            for (int i = 0; i < 120; i++) ResultShuffle[i] = "";
            if (strOrg == "") return "";
            strOrg = EncryptData(strOrg);
            ShuffleString(strOrg, 0);
            strOrg = "";
            for (int i = 0; i < 120; i++) strOrg += ResultShuffle[i].Trim();
            char ichr;
            int intval;
            string strCode = "";
            for (int i = 0; i < strOrg.Length; i++)
            {
                ichr = strOrg[i];
                intval = Convert.ToInt16(ichr);
                if ((intval >= 65 && intval <= 90) || (intval >= 97 && intval <= 122)) strCode += ichr.ToString();
            }
            strCode = strCode.Substring(0, 30).ToUpper();
            return strCode;
        }

        public bool checkLicense(string activationCode, string activationKey)
        {
            string newActivationCode = GenerateCode(RemoveMask(activationCode));

            return newActivationCode.Equals(RemoveMask(activationKey));
        }

        private string RemoveMask(string strOrg)
        {
            strOrg = strOrg.Replace(" - ", "");
            return strOrg;
        }

        /// <summary>
        /// Gets the current DateTime from time-a.nist.gov.
        /// </summary>
        /// <returns>A DateTime containing the current time.</returns>
        public DateTime? GetNetworkTime()
        {
            return GetNetworkTime("time.windows.com"); // time-a.nist.gov
        }

        /// <summary>
        /// Gets the current DateTime from <paramref name="ntpServer"/>.
        /// </summary>
        /// <param name="ntpServer">The hostname of the NTP server.</param>
        /// <returns>A DateTime containing the current time.</returns>
        private DateTime? GetNetworkTime(string ntpServer)
        {
            try
            {
                IPAddress[] address = Dns.GetHostEntry(ntpServer).AddressList;

                if (address == null || address.Length == 0) return null;

                IPEndPoint ep = new IPEndPoint(address[0], 123);

                return GetNetworkTime(ep);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Gets the current DateTime form <paramref name="ep"/> IPEndPoint.
        /// </summary>
        /// <param name="ep">The IPEndPoint to connect to.</param>
        /// <returns>A DateTime containing the current time.</returns>
        private DateTime GetNetworkTime(IPEndPoint ep)
        {
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            s.Connect(ep);

            byte[] ntpData = new byte[48]; // RFC 2030 
            ntpData[0] = 0x1B;
            for (int i = 1; i < 48; i++)
                ntpData[i] = 0;

            s.Send(ntpData);
            s.Receive(ntpData);

            byte offsetTransmitTime = 40;
            ulong intpart = 0;
            ulong fractpart = 0;

            for (int i = 0; i <= 3; i++)
                intpart = 256 * intpart + ntpData[offsetTransmitTime + i];

            for (int i = 4; i <= 7; i++)
                fractpart = 256 * fractpart + ntpData[offsetTransmitTime + i];

            ulong milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L);
            s.Close();

            TimeSpan timeSpan = TimeSpan.FromTicks((long)milliseconds * TimeSpan.TicksPerMillisecond);

            DateTime dateTime = new DateTime(1900, 1, 1);
            dateTime += timeSpan;

            TimeSpan offsetAmount = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);
            DateTime networkDateTime = (dateTime + offsetAmount);

            return networkDateTime;
        }
    }
}
